{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PdKwzEluDBN7"
      },
      "source": [
        "# Install openai-agents SDK"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 48,
      "metadata": {
        "id": "3QdkOviEB2ay"
      },
      "outputs": [],
      "source": [
        "!pip install -Uq openai-agents"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7yD91lz4DIAx"
      },
      "source": [
        "# Make your Notebook capable of running asynchronous functions.\n",
        "Both Jupyter notebooks and Python’s asyncio library utilize event loops, but they serve different purposes and can sometimes interfere with each other.\n",
        "\n",
        "The nest_asyncio library allows the existing event loop to accept nested event loops, enabling asyncio code to run within environments that already have an event loop, such as Jupyter notebooks.\n",
        "\n",
        "In summary, both Jupyter notebooks and Python’s asyncio library utilize event loops to manage asynchronous operations. When working within Jupyter notebooks, it’s essential to be aware of the existing event loop to effectively run asyncio code without conflicts."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 49,
      "metadata": {
        "id": "C8YXyIpiZ9v4"
      },
      "outputs": [],
      "source": [
        "import nest_asyncio\n",
        "nest_asyncio.apply()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wQsVowow7ihQ"
      },
      "source": [
        "# Config"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "metadata": {
        "id": "XnusaX_RWF22"
      },
      "outputs": [],
      "source": [
        "from agents import (\n",
        "    AsyncOpenAI,\n",
        "    OpenAIChatCompletionsModel,\n",
        ")\n",
        "from google.colab import userdata\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 51,
      "metadata": {
        "id": "oPvcFwItoKqw"
      },
      "outputs": [],
      "source": [
        "gemini_api_key = userdata.get(\"GEMINI_API_KEY\")\n",
        "\n",
        "\n",
        "# Check if the API key is present; if not, raise an error\n",
        "if not gemini_api_key:\n",
        "    raise ValueError(\"GEMINI_API_KEY is not set. Please ensure it is defined in your .env file.\")\n",
        "\n",
        "#Reference: https://ai.google.dev/gemini-api/docs/openai\n",
        "external_client = AsyncOpenAI(\n",
        "    api_key=gemini_api_key,\n",
        "    base_url=\"https://generativelanguage.googleapis.com/v1beta/openai/\",\n",
        ")\n",
        "\n",
        "model = OpenAIChatCompletionsModel(\n",
        "    model=\"gemini-2.0-flash\",\n",
        "    openai_client=external_client\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 52,
      "metadata": {
        "id": "y9LkW-F7nC3T"
      },
      "outputs": [],
      "source": [
        "from agents import set_default_openai_client, set_tracing_disabled\n",
        "\n",
        "set_default_openai_client(external_client)\n",
        "set_tracing_disabled(True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rWL7EnI_7mIF"
      },
      "source": [
        "# Learning LifeCycle"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 53,
      "metadata": {
        "id": "xL1SE0WBzNfB"
      },
      "outputs": [],
      "source": [
        "# Imports\n",
        "import asyncio\n",
        "import random\n",
        "from typing import Any\n",
        "\n",
        "from agents import Agent, RunContextWrapper, RunHooks, Runner, Tool, Usage, function_tool"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZF1dd25XzEBp"
      },
      "source": [
        "### 1. Basic Example (Understand Core Concept)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 54,
      "metadata": {
        "id": "gfScTeRmzQYS"
      },
      "outputs": [],
      "source": [
        "class TestHooks(RunHooks):\n",
        "    def __init__(self):\n",
        "        self.event_counter = 0\n",
        "        self.name = \"TestHooks\"\n",
        "\n",
        "    async def on_agent_start(self, context: RunContextWrapper, agent: Agent) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(f\"### {self.name} {self.event_counter}: Agent {agent.name} started. Usage: {context.usage}\")\n",
        "\n",
        "    async def on_agent_end(self, context: RunContextWrapper, agent: Agent, output: Any) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(f\"### {self.name} {self.event_counter}: Agent {agent.name} ended. Usage: {context.usage}, Output: {output}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 55,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "CzedWWWrzfQD",
        "outputId": "fc4f2286-5557-484f-db2a-02bd31e79a55"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "### TestHooks 1: Agent Content Moderator Agent started. Usage: Usage(requests=0, input_tokens=0, output_tokens=0, total_tokens=0)\n",
            "### TestHooks 2: Agent Content Moderator Agent ended. Usage: Usage(requests=1, input_tokens=47, output_tokens=87, total_tokens=134), Output: This tweet expresses a question about the future of \"Agentic AI.\" It doesn't violate any obvious content policies, but it's a question about AI and could benefit from an answer.\n",
            "\n",
            "**Flag for AI Assistance/Response:**  Potentially. The user is asking a question about the future of a specific type of AI.  Providing a response (perhaps with a disclaimer about predicting the future) would be helpful.\n",
            "\n",
            "This tweet expresses a question about the future of \"Agentic AI.\" It doesn't violate any obvious content policies, but it's a question about AI and could benefit from an answer.\n",
            "\n",
            "**Flag for AI Assistance/Response:**  Potentially. The user is asking a question about the future of a specific type of AI.  Providing a response (perhaps with a disclaimer about predicting the future) would be helpful.\n",
            "\n",
            "--end--\n"
          ]
        }
      ],
      "source": [
        "start_hook = TestHooks()\n",
        "\n",
        "start_agent = Agent(\n",
        "    name=\"Content Moderator Agent\",\n",
        "    instructions=\"You are content moderation agent. Watch social media content received and flag queries that need help or answer. We will answer anything about AI?\",\n",
        "    model=model\n",
        ")\n",
        "\n",
        "async def main():\n",
        "  result = await Runner.run(\n",
        "      start_agent,\n",
        "      hooks=start_hook,\n",
        "      input=f\"<tweet>Will Agentic AI Die at end of 2025?.</tweet>\"\n",
        "  )\n",
        "\n",
        "  print(result.final_output)\n",
        "\n",
        "asyncio.run(main())\n",
        "print(\"--end--\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pqF1gaVZ2R0l"
      },
      "source": [
        "We can add callbacks on various lifecycle events in an agent run listed here:\n",
        "\n",
        "https://openai.github.io/openai-agents-python/ref/lifecycle/#agents.lifecycle.RunHooks"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cM8n3d4GzGGz"
      },
      "source": [
        "### 2. Advanced Example (With Tools and Agents HandOff)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 57,
      "metadata": {
        "id": "2XzWlsI2yue2"
      },
      "outputs": [],
      "source": [
        "class ExampleHooks(RunHooks):\n",
        "    def __init__(self):\n",
        "        self.event_counter = 0\n",
        "\n",
        "    def _usage_to_str(self, usage: Usage) -> str:\n",
        "        return f\"{usage.requests} requests, {usage.input_tokens} input tokens, {usage.output_tokens} output tokens, {usage.total_tokens} total tokens\"\n",
        "\n",
        "    async def on_agent_start(self, context: RunContextWrapper, agent: Agent) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### {self.event_counter}: Agent {agent.name} started. Usage: {self._usage_to_str(context.usage)}\"\n",
        "        )\n",
        "\n",
        "    async def on_agent_end(self, context: RunContextWrapper, agent: Agent, output: Any) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### {self.event_counter}: Agent {agent.name} ended with output {output}. Usage: {self._usage_to_str(context.usage)}\"\n",
        "        )\n",
        "\n",
        "    async def on_tool_start(self, context: RunContextWrapper, agent: Agent, tool: Tool) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### {self.event_counter}: Tool {tool.name} started. Usage: {self._usage_to_str(context.usage)}\"\n",
        "        )\n",
        "\n",
        "    async def on_tool_end(\n",
        "        self, context: RunContextWrapper, agent: Agent, tool: Tool, result: str\n",
        "    ) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### {self.event_counter}: Tool {tool.name} ended with result {result}. Usage: {self._usage_to_str(context.usage)}\"\n",
        "        )\n",
        "\n",
        "    async def on_handoff(\n",
        "        self, context: RunContextWrapper, from_agent: Agent, to_agent: Agent\n",
        "    ) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### {self.event_counter}: Handoff from {from_agent.name} to {to_agent.name}. Usage: {self._usage_to_str(context.usage)}\"\n",
        "        )"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 59,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "S11ItAh-resv",
        "outputId": "d8981760-fc23-4645-9797-cb752a4e8cd1"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Enter a max number: 3\n",
            "### 1: Agent Start Agent started. Usage: 0 requests, 0 input tokens, 0 output tokens, 0 total tokens\n",
            "### 2: Tool random_number started. Usage: 1 requests, 73 input tokens, 4 output tokens, 77 total tokens\n",
            "### 3: Tool random_number ended with result 1. Usage: 1 requests, 73 input tokens, 4 output tokens, 77 total tokens\n",
            "### 4: Handoff from Start Agent to Multiply Agent. Usage: 2 requests, 155 input tokens, 31 output tokens, 186 total tokens\n",
            "### 5: Agent Multiply Agent started. Usage: 2 requests, 155 input tokens, 31 output tokens, 186 total tokens\n",
            "### 6: Tool multiply_by_two started. Usage: 3 requests, 242 input tokens, 51 output tokens, 293 total tokens\n",
            "### 7: Tool multiply_by_two ended with result 2. Usage: 3 requests, 242 input tokens, 51 output tokens, 293 total tokens\n",
            "### 8: Agent Multiply Agent ended with output The final result is 2.\n",
            ". Usage: 4 requests, 356 input tokens, 59 output tokens, 415 total tokens\n",
            "The final result is 2.\n",
            "\n",
            "Done!\n"
          ]
        }
      ],
      "source": [
        "hooks = ExampleHooks()\n",
        "\n",
        "\n",
        "@function_tool(\"random_number\")\n",
        "def random_number(max: int) -> int:\n",
        "    \"\"\"Generate a random number up to the provided max.\"\"\"\n",
        "    return random.randint(0, max)\n",
        "\n",
        "\n",
        "@function_tool(\"multiply_by_two\")\n",
        "def multiply_by_two(x: int) -> int:\n",
        "    \"\"\"Return x times two.\"\"\"\n",
        "    return x * 2\n",
        "\n",
        "\n",
        "multiply_agent = Agent(\n",
        "    name=\"Multiply Agent\",\n",
        "    instructions=\"Multiply the number by 2 and then return the final result.\",\n",
        "    tools=[multiply_by_two],\n",
        "    model=model\n",
        ")\n",
        "\n",
        "start_agent = Agent(\n",
        "    name=\"Start Agent\",\n",
        "    instructions=\"Generate a random number. If it's even, stop. If it's odd, hand off to the multipler agent.\",\n",
        "    tools=[random_number],\n",
        "    handoffs=[multiply_agent],\n",
        "    model=model\n",
        ")\n",
        "\n",
        "\n",
        "async def main() -> None:\n",
        "    user_input = input(\"Enter a max number: \")\n",
        "    ans = await Runner.run(\n",
        "        start_agent,\n",
        "        hooks=hooks,\n",
        "        input=f\"Generate a random number between 0 and {user_input}.\",\n",
        "    )\n",
        "\n",
        "    print(ans.final_output)\n",
        "\n",
        "    print(\"Done!\")\n",
        "\n",
        "asyncio.run(main())"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
